﻿using System;
using System.Reflection;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection.Emit;

namespace SlamCms.Common
{
	public static class TypeExtensions
	{
		public static T CreateInstance<T>(this Type type) where T : class
		{
			var target = type.GetConstructor(Type.EmptyTypes);
			var dynamic = new DynamicMethod(string.Empty,
						  type,
						  new Type[0],
						  target.DeclaringType);
			var il = dynamic.GetILGenerator();
			il.DeclareLocal(target.DeclaringType);
			il.Emit(OpCodes.Newobj, target);
			il.Emit(OpCodes.Stloc_0);
			il.Emit(OpCodes.Ldloc_0);
			il.Emit(OpCodes.Ret);

			var method = (Func<T>)dynamic.CreateDelegate(typeof(Func<T>));
			return method();
		}

		public static Assembly GetAssembly(this Type type)
		{
			return Assembly.GetAssembly(type);
		}

		public static bool Is<T>(this Type type)
		{
			return typeof(T).IsAssignableFrom(type);
		}

		public static bool IsSystemType(this Type type)
		{
			return type.In(typeof(short), typeof(short?), typeof(ushort), typeof(ushort?),
						   typeof(int), typeof(int?), typeof(uint), typeof(uint?),
						   typeof(long), typeof(long?), typeof(ulong), typeof(ulong?),
						   typeof(bool), typeof(bool?),
						   typeof(decimal), typeof(decimal?),
						   typeof(float), typeof(float?),
						   typeof(double), typeof(double?),
						   typeof(DateTime), typeof(DateTime?),
						   typeof(char), typeof(char?),
						   typeof(string),
						   typeof(Guid));
		}
	}
}
